package pv;

/**
 * 多生产者 - 多消费者
 * <p>
 *     解决该问题的关键在于理清复杂的同步关系
 *     从单个进程的角度考虑, 会有以下结论:
 *     如果盘子里装有苹果, 那么一定要女儿取走苹果后父亲或母亲才能再放入水果
 *     如果盘子里装有橘子, 那么一定要儿子取走苹果后父亲或母亲才能再放入水果
 *     这么看是否就意味着要设置 4 个同步信号量分别实现这四个“一前一后”的关系了？
 *     正确的分析法应该从“事件”的角度来考虑, 把上述四对“进程行为的前后关系”抽象为
 *     盘子变空事件 -> 放入水果事件
 *     盘子变空, 可以由儿子或者女儿
 * </p>
 * <p>
 * 爸爸往盘子里放苹果，女儿从盘子里取苹果
 * 妈妈往盘子里放橘子，儿子从盘子里取橘子
 * 盘子为空, 爸爸妈妈才能往盘子里放东西
 * </p>
 * <p>
 * 爸爸与妈妈是互斥关系
 * 爸爸与女儿、妈妈与儿子是同步关系
 * 儿子、女儿与爸爸、妈妈 是同步关系
 * </p>
 *
 * @author yezh
 * @date 2024/7/3 17:22
 */
public class MulProductAMulConsum {

    private static final Semaphore apple = new Semaphore(0, "apple");
    private static final Semaphore orange = new Semaphore(0, "orange");
    private static final Semaphore plate = new Semaphore(1, "plate");
    // 实现互斥访问盘子, 因为盘子里只能放一个资源, 所以这个信号量可以去掉; 如果有多个资源, 就需要这个信号量
    private static final Semaphore mutex = new Semaphore(1, "mutex");

    public static void main(String[] args) {
        new SleepLoopThread(MulProductAMulConsum::father).start();
        new SleepLoopThread(MulProductAMulConsum::mother).start();
        new SleepLoopThread(MulProductAMulConsum::son).start();
        new SleepLoopThread(MulProductAMulConsum::daughter).start();
    }

    private static void father() {
        plate.p();
        mutex.p();
        System.out.println("爸爸放入苹果");
        mutex.v();
        apple.v();
    }

    private static void mother() {
        plate.p();
        mutex.p();
        System.out.println("妈妈放入橘子");
        mutex.v();
        orange.v();
    }

    private static void son() {
        orange.p();
        mutex.p();
        System.out.println("儿子拿走橘子");
        mutex.v();
        plate.v();
    }

    private static void daughter() {
        apple.p();
        mutex.p();
        System.out.println("女儿拿走苹果");
        mutex.v();
        plate.v();
    }



}
